package com.mida.dms.knw.service.impl;


import com.mida.dms.knw.Result.BaseResult;
import com.mida.dms.knw.config.enumData.FrontendReportRule;
import com.mida.dms.knw.entity.KnwIndividual;
import com.mida.dms.knw.entity.KnwIndividualSolt;
import com.mida.dms.knw.entity.vo.*;
import com.mida.dms.knw.mapper.KnwIndividualMapper;
import com.mida.dms.knw.mapper.KnwIndividualSoltMapper;
import com.mida.dms.knw.mapper.KnwSlotMapper;
import com.mida.dms.knw.service.KnwIndividualService;
import com.mida.dms.knw.service.SoidService;
import com.mida.dms.knw.util.CharTransFormUtil;
import com.mida.dms.knw.util.CharacterConstant;
import com.mida.dms.knw.util.DataSetConstants;
import com.mida.dms.knw.vo.IndividualParmVo;
import com.mida.dms.knw.vo.KnwIndividualPageVo;
import com.mida.dms.knw.vo.Page;
import com.mida.dms.knw.vo.PageResultVo;
import com.mida.tool.common.result.ActionResult;
import com.mida.tool.common.result.ListResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.time.StopWatch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
@Slf4j
@Transactional(value = "dtdTxManager", rollbackFor = Exception.class)
public class KnwIndividualServiceImpl extends BaseResult implements KnwIndividualService {

    /**
     * Logger
     */
    private final Logger logger = LoggerFactory.getLogger(getClass());


    @Autowired
    private KnwIndividualMapper knwIndividualMapper;
    @Autowired
    private KnwIndividualSoltMapper knwIndividualSoltMapper;
    @Autowired
    private SoidService soidService;


    /**
     * knwSlotMapper
     */
    @Autowired
    private KnwSlotMapper knwSlotMapper;


    /**
     * arrayLists
     */
    private List<String[]> arrayLists;

    /**
     * 删除实例
     *
     * @return
     */
    @Override
    public ActionResult delete(long soid) throws Exception {
        log.info("开始删除实例" + soid);
        ActionResult actionResult = new ActionResult();
        String[] strSoids;

        if (StringUtils.isEmpty(String.valueOf(soid))) {
            actionResult.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            actionResult.setMessage("实例Soid不能为空");
            return actionResult;
        }
        knwIndividualMapper.deleteByPrimaryKey(soid);
        knwIndividualSoltMapper.deleteByIndividualSoid(soid);
        return buildActionSuccess();
    }

    /**
     * 批量禁用
     *
     * @return
     */
    @Override
    public ActionResult stopSize(String soids) throws Exception {
        log.info("开始批量禁用实例" + soids);
        ActionResult actionResult = new ActionResult();
        String[] strSoids;

        if (StringUtils.isEmpty(String.valueOf(soids))) {
            actionResult.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            actionResult.setMessage("实例Soid不能为空");
            return actionResult;
        }
        strSoids = soids.split(CharacterConstant.COMMA_SYMBOL);
        Long status = DataSetConstants.STOP;
        for (String strSoid : strSoids) {
            if (StringUtils.isEmpty(strSoid)) {
                continue;
            }
            knwIndividualMapper.updateByIndividualSoid(Long.valueOf(strSoid), status);
            knwIndividualSoltMapper.updateByIndividualSoid(Long.valueOf(strSoid), status);
        }

        return buildActionSuccess();

    }

    /**
     * 批量启用
     *
     * @return
     */
    @Override
    public ActionResult openSize(String soids) throws Exception {
        log.info("开始批量启用实例" + soids);
        ActionResult actionResult = new ActionResult();
        String[] strSoids;
        if (StringUtils.isEmpty(String.valueOf(soids))) {
            actionResult.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            actionResult.setMessage("实例Soid不能为空");
            return actionResult;
        }
        strSoids = soids.split(CharacterConstant.COMMA_SYMBOL);
        Long status = DataSetConstants.START;
        for (String strSoid : strSoids) {
            if (StringUtils.isEmpty(strSoid)) {
                continue;
            }
            knwIndividualMapper.updateByIndividualSoid(Long.valueOf(strSoid), status);
            knwIndividualSoltMapper.updateByIndividualSoid(Long.valueOf(strSoid), status);
        }

        return buildActionSuccess();

    }

    @Override
    public ListResult<PageResultVo<KnwIndividualVo>> findPage(KnwIndividualPageVo vo) {
        log.info("开始实例分页查询,查询条件: " + vo.toString());
        ListResult result = new ListResult();
        PageResultVo pageResultVo = new PageResultVo();
        Page page = new Page(vo.getCurrentPage(), vo.getPageSize());
        pageResultVo.setPage(page);
        StopWatch stopWatch = StopWatch.createStarted();
        List<KnwIndividualVo> list = null;

        if (vo.getNoumenonSoid() == null) {
            result.setData(pageResultVo);
            result.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            result.setMessage("本体soid不能为空");
            return result;
        }

        try {
            KnwIndividualPage kpage = new KnwIndividualPage(vo.getCurrentPage(), vo.getPageSize(), vo.getSearChData().trim());
            kpage.setNoumenonSoid(vo.getNoumenonSoid());
            //根据本体Soid、slot值查询
            int count = knwIndividualMapper.findPageCount(kpage);
            if (count > 0) {
                page.setTotalCount(count);
                list = knwIndividualMapper.getKnwIndividualPage(kpage);

                Map<Long, Object> map;
                for (KnwIndividualVo kiv : list) {
                    if (kiv.getIndividualSoid() != null) {
                        List<KnwIndividualSolt> listKnwIndividualSolt =
                                knwIndividualSoltMapper.getKnwIndividualSolts(kiv.getIndividualSoid());

                        if (listKnwIndividualSolt != null && listKnwIndividualSolt.size() > 0) {
                            map = new HashMap<Long, Object>();
                            SoltVo soltVo;
                            List<SoltVo> soltVos;
                            for (KnwIndividualSolt s : listKnwIndividualSolt) {
                                if (map.get(s.getSlotSoid()) == null) {
                                    soltVos = new ArrayList<SoltVo>();
                                    soltVo = new SoltVo(s);
                                    soltVos.add(soltVo);
                                    map.put(s.getSlotSoid(), soltVos);
                                } else {
                                    List<SoltVo> tmp = (List<SoltVo>) map.get(s.getSlotSoid());
                                    soltVo = new SoltVo(s);
                                    tmp.add(soltVo);
                                    map.put(s.getSlotSoid(), tmp);
                                }
                            }

                            List<KnwIndividualSoltVo> tmpKis = new ArrayList<KnwIndividualSoltVo>();
                            KnwIndividualSoltVo knwIndividualSoltVo;
                            for (Map.Entry<Long, Object> entry : map.entrySet()) {
                                knwIndividualSoltVo = new KnwIndividualSoltVo();
                                knwIndividualSoltVo.setSlotSoid(entry.getKey());
                                List<SoltVo> listTmp = (List<SoltVo>) entry.getValue();
                                if (listTmp != null && listTmp.size() > 0) {
                                    knwIndividualSoltVo.setBasic(listTmp.get(0).getBasic());
                                    knwIndividualSoltVo.setDataType(listTmp.get(0).getDataType());
//                                    knwIndividualSoltVo.setDerailCodingSystemSoid(listTmp.get(0).getDerailCodingSystemSoid());
                                }
                                knwIndividualSoltVo.setList((List<SoltVo>) entry.getValue());
                                tmpKis.add(knwIndividualSoltVo);
                            }

                            kiv.setListKnwIndividualSoltVo(tmpKis);
                        }
                    }
                }
            } else {
                pageResultVo.setPage(null);
            }

            pageResultVo.setList(list);
            buildListSuccess(result, pageResultVo);
        } catch (Exception e) {
            list = new ArrayList<KnwIndividualVo>(0);
            pageResultVo.setList(list);
            log.error("分页查询实例发生异常" + e.getMessage());
            buildListWarn(result, e);
        } finally {
            stopWatch.stop();
            log.info("本次分页查询耗时: " + stopWatch.getTime() + "ms");
        }
        return result;
    }

    /**
     * 查询本体下所有实例
     */
    @Override
    public ListResult<List<KnwIndividualVo>> findAll(KnwIndividualPageVo vo) {
        log.info("开始实例分页查询,查询条件: " + vo.toString());
        ListResult result = new ListResult();
        PageResultVo pageResultVo = new PageResultVo();
        StopWatch stopWatch = StopWatch.createStarted();
        List<KnwIndividualVo> list = null;
        if (vo.getNoumenonSoid() == null) {
            vo.setNoumenonSoid(20207742773886976l);//设置医学影像学诊断本体
        }

        try {
            //根据本体Soid、slot值查询
            list = knwIndividualMapper.getKnwIndividualAll(vo.getSearChData().trim(), vo.getNoumenonSoid());

            Map<Long, Object> map;
            for (KnwIndividualVo kiv : list) {
                if (kiv.getIndividualSoid() != null) {
                    List<KnwIndividualSoltVos> listKnwIndividualSolt =
                            knwIndividualSoltMapper.getKnwIndividualSoltVos(kiv.getIndividualSoid());

                    if (listKnwIndividualSolt != null && listKnwIndividualSolt.size() > 0) {
                        map = new HashMap<Long, Object>();
                        SoltVo soltVo;
                        List<SoltVo> soltVos;
                        for (KnwIndividualSoltVos s : listKnwIndividualSolt) {
                            if (map.get(s.getSlotSoid()) == null) {
                                soltVos = new ArrayList<SoltVo>();
                                soltVo = new SoltVo(s);
                                soltVos.add(soltVo);
                                map.put(s.getSlotSoid(), soltVos);
                            } else {
                                List<SoltVo> tmp = (List<SoltVo>) map.get(s.getSlotSoid());
                                soltVo = new SoltVo(s);
                                tmp.add(soltVo);
                                map.put(s.getSlotSoid(), tmp);
                            }
                        }
                        List<KnwIndividualSoltVo> tmpKis = new ArrayList<KnwIndividualSoltVo>();
                        KnwIndividualSoltVo knwIndividualSoltVo;
                        for (Map.Entry<Long, Object> entry : map.entrySet()) {
                            knwIndividualSoltVo = new KnwIndividualSoltVo();
                            knwIndividualSoltVo.setSlotSoid(entry.getKey());
                            List<SoltVo> listTmp = (List<SoltVo>) entry.getValue();
                            if (listTmp != null && listTmp.size() > 0) {
                                knwIndividualSoltVo.setBasic(listTmp.get(0).getBasic());
                                knwIndividualSoltVo.setDataType(listTmp.get(0).getDataType());
//                                    knwIndividualSoltVo.setDerailCodingSystemSoid(listTmp.get(0).getDerailCodingSystemSoid());
                                knwIndividualSoltVo.setSlotName(listTmp.get(0).getSlotName());

                            }
                            knwIndividualSoltVo.setList((List<SoltVo>) entry.getValue());
                            tmpKis.add(knwIndividualSoltVo);
                        }

                        kiv.setListKnwIndividualSoltVo(tmpKis);
                    }
                }
            }

            buildListSuccess(result, list);
        } catch (Exception e) {
            list = new ArrayList<KnwIndividualVo>(0);
            pageResultVo.setList(list);
            log.error("分页查询实例发生异常" + e.getMessage());
            buildListWarn(result, e);
        } finally {
            stopWatch.stop();
            log.info("本次分页查询耗时: " + stopWatch.getTime() + "ms");
        }
        return result;
    }

    @Override
    public ActionResult save(KnwIndividualVo t) throws Exception {
        log.info("开始保存实例");
        ActionResult actionResult = new ActionResult();
        List<Long> units = new ArrayList<Long>();
        units.add(394L);//g/L
        units.add(393L);//ML
        units.add(392L);//L
        units.add(386L);//毫克
        units.add(385L);//克
        units.add(384L);//千克
        units.add(383L);//毫米
        units.add(382L);//厘米
        units.add(381L);//米
        units.add(380L);//戈
        units.add(379L);//摄氏度
        units.add(378L);//百分率

        if (t == null) {
            actionResult.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            actionResult.setMessage("实例不能为空");
            return actionResult;
        }
        if (t.getListKnwIndividualSoltVo().size() == 0) {
            actionResult.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            actionResult.setMessage("参数错误，请校验");
            return actionResult;
        }
        for (KnwIndividualSoltVo knwIndividualSoltVo : t.getListKnwIndividualSoltVo()) {

            if (knwIndividualSoltVo.getBasic() < knwIndividualSoltVo.getList().size()) {
                actionResult.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
                actionResult.setMessage("绑定的值集数量超出基数范围");
                return actionResult;
            }
            if (knwIndividualSoltVo.getDerailCodingSystemSoid() == null
                    && knwIndividualSoltVo.getUnit() != null
                    && units.contains(knwIndividualSoltVo.getUnit())) {//是否进行校验
                if (knwIndividualSoltVo.getList().size() != 0) {
                    for (SoltVo soltVo : knwIndividualSoltVo.getList()) {

                        if (soltVo.getDataValue() != null && !soltVo.getDataValue().matches("-?[0-9]+\\.?[0-9]*")) {//校验是否为数字
                            actionResult.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
                            actionResult.setMessage("须输入纯数字");
                            return actionResult;
                        }
                    }
                }
            }
        }
        if (t.getIndividualSoid() == null) {//新增保存
            //1、保存实例基本信息
            KnwIndividual knwIndividual = new KnwIndividual();
//            Long seq = oIDGanerator.getSOID();
            Long seq = soidService.getSoid();
            knwIndividual.setIndividualSoid(seq);//实例soid
            knwIndividual.setNoumenonSoid(t.getNoumenonSoid());//本体soid
            knwIndividual.setIndividualName(t.getIndividualName());//实例名称
            knwIndividual.setPyCode(CharTransFormUtil.toPinyinSimple(t.getIndividualName()));
            knwIndividual.setWbCode(CharTransFormUtil.toWubi(t.getIndividualName()));
            knwIndividual.setIsDelete(0L);
            knwIndividual.setStatus(t.getStatus());
            knwIndividual.setCreateDate(new Date());
            knwIndividual.setLable(FrontendReportRule.TAG_LABEL.getCodeName());
            knwIndividualMapper.insertSelective(knwIndividual);

            soidService.insertOid(seq, 1);
//            String oid = oIDGanerator.getOID(0);
//            DtOid dtOid = new DtOid();
//            dtOid.setOid(oid);
//            dtOid.setSoid(seq);
//            dtOidMapper.insert(dtOid);

            //2、保存solt信息
            if (SaveSlot(actionResult, t, seq)) {
                return actionResult;
            }

        } else {//更新保存
            KnwIndividual knwIndividual = knwIndividualMapper.selectByPrimaryKey(t.getIndividualSoid());
            if (knwIndividual != null) {//更新实例基本信息
                KnwIndividual knwIndividualT = new KnwIndividual();
                knwIndividualT.setIndividualSoid(knwIndividual.getIndividualSoid());
                if (!knwIndividual.getIndividualName().equals(t.getIndividualName())) {//实例名称修改
                    knwIndividualT.setIndividualName(t.getIndividualName());//实例名称
                    knwIndividualT.setPyCode(CharTransFormUtil.toPinyinSimple(t.getIndividualName()));
                    knwIndividualT.setWbCode(CharTransFormUtil.toWubi(t.getIndividualName()));
                }
                knwIndividualT.setStatus(t.getStatus());
                knwIndividualT.setUpdateDate(new Date());
                knwIndividualMapper.updateByPrimaryKeySelective(knwIndividualT);
            }
            //1、先删除实例slot
            knwIndividualSoltMapper.deleteByIndividualSoid(t.getIndividualSoid());
            //2、保存实例slot
            if (SaveSlot(actionResult, t, t.getIndividualSoid())) {
                return actionResult;
            }
        }
        return buildActionSuccess();
    }

    /**
     * 开始批量保存实例
     *
     * @param knwIndividualVos
     * @return
     * @throws Exception
     */
    @Override
    public ActionResult saveKnwIndividualSolt(KnwIndividualVos knwIndividualVos) throws Exception {
        log.info("开始批量保存实例");
        ActionResult actionResult = new ActionResult();

        if (knwIndividualVos == null) {
            actionResult.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            actionResult.setMessage("实例不能为空");
            return actionResult;
        }
        if (knwIndividualVos.getListKnwIndividualVos() == null &&
                knwIndividualVos.getListKnwIndividualVos().size() == 0) {
            actionResult.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            actionResult.setMessage("参数错误，请校验");
            return actionResult;
        }

        for (KnwIndividualVo k : knwIndividualVos.getListKnwIndividualVos()) {

            if (k.getIndividualSoid() == null) {
                KnwIndividual knwIndividual = new KnwIndividual();
//                Long seq = oIDGanerator.getSOID();
                Long seq = soidService.getSoid();
                knwIndividual.setIndividualSoid(seq);//实例soid
                knwIndividual.setNoumenonSoid(k.getNoumenonSoid());//本体soid
                knwIndividual.setIndividualName(k.getIndividualName());//实例名称
                knwIndividual.setPyCode(CharTransFormUtil.toPinyinSimple(k.getIndividualName()));
                knwIndividual.setWbCode(CharTransFormUtil.toWubi(k.getIndividualName()));
                knwIndividual.setIsDelete(0L);
                knwIndividual.setStatus(147L);
                knwIndividual.setCreateDate(new Date());
                knwIndividual.setLable(FrontendReportRule.TAG_LABEL.getCodeName());
                knwIndividualMapper.insertSelective(knwIndividual);

                soidService.insertOid(seq, 1);
//                String oid = oIDGanerator.getOID(0);
//                DtOid dtOid = new DtOid();
//                dtOid.setOid(oid);
//                dtOid.setSoid(seq);
//                dtOidMapper.insert(dtOid);

                k.setStatus(147L);
                //2、保存solt信息
                if (SaveSlot(actionResult, k, seq)) {
                    return actionResult;
                }
            }

        }

        return buildActionSuccess();
    }

    @Override
    public ListResult<PageResultVo<KnwIndividualVo>> getKnwIndividualPage(KnwIndividualPageVo vo) {
        log.info("开始实例分页查询,查询条件: " + vo.toString());
        ListResult result = new ListResult();
        PageResultVo pageResultVo = new PageResultVo();
        Page page = new Page(vo.getCurrentPage(), vo.getPageSize());
        pageResultVo.setPage(page);
        StopWatch stopWatch = StopWatch.createStarted();
        List<KnwIndividualVo> list = null;

        try {
            KnwIndividualPage kpage = new KnwIndividualPage(vo.getCurrentPage(), vo.getPageSize(), vo.getSearChData().trim().toUpperCase());
            kpage.setNoumenonSoid(vo.getNoumenonSoid());
            //根据本体Soid、slot值查询
            int count = knwIndividualMapper.findPageCount(kpage);
            if (count > 0) {
                page.setTotalCount(count);
                list = knwIndividualMapper.getKnwIndividualPage(kpage);
            }

            pageResultVo.setList(list);
            buildListSuccess(result, pageResultVo);
        } catch (Exception e) {
            list = new ArrayList<KnwIndividualVo>(0);
            pageResultVo.setList(list);
            log.error("分页查询实例发生异常" + e.getMessage());
            buildListWarn(result, e);
        } finally {
            stopWatch.stop();
            log.info("本次分页查询耗时: " + stopWatch.getTime() + "ms");
        }
        return result;
    }

    /**
     * 初始化实例生成页面
     *
     * @param noumenonSoid
     * @return
     */
    @Override
    public ListResult<List<KnwSlotVo>> showIndividualInit(Long noumenonSoid) {

        log.info("开始根据本体soid、查询本体Slot对应的编码体系" + noumenonSoid);
        StopWatch stopWatch = StopWatch.createStarted();
        ListResult listResult = new ListResult();

        if (ObjectUtils.isEmpty(noumenonSoid)) {
            log.error("本体soid不能为空");
            buildBadRequestListWarn(listResult, "本体soid不能为空");
            return listResult;
        }
        List<KnwSlotVo> list = null;
        try {
            list = knwSlotMapper.selectAllSlotVoByNoumenonSoid(noumenonSoid);
            buildListSuccess(listResult, list);
        } catch (Exception e) {
            log.error("根据本体soid、查询本体Slot对应的编码体系异常", e);
            buildListWarn(listResult, "查询所有本体Slot失败");
        } finally {
            stopWatch.stop();
            log.info("本次查询耗时:" + stopWatch.getTime() + "ms");
        }
        return listResult;
    }

    /**
     * 实例列表生成
     *
     * @param individualParmVo
     * @return
     */
    @Override
    public ListResult<List<KnwSlotVo>> getIndividualList(IndividualParmVo individualParmVo) {

//        log.info("开始实例列表生成" + individualParmVo.getDerailCodingSystemSoids());
//        StopWatch stopWatch = StopWatch.createStarted();
        ListResult listResult = new ListResult();
//
//        if (ObjectUtils.isEmpty(individualParmVo.getDerailCodingSystemSoids())) {
//            log.error("编码体系soid不能为空");
//            buildBadRequestListWarn(listResult, "编码体系soid不能为空");
//            return listResult;
//        }
//        List<KnwSlotVo> list = null;
//        List<String> listTmps = new ArrayList<>();
//        List<KnwSlotVo> listKnwSlotVoTmp = null;
//        try {
//            // 根据本体soid，取得本体SLOT以及相关编码体系列表
//       //     list = knwSlotMapper.selectAllSlotVoByNoumenonSoid(individualParmVo.getNoumenonSoid());
//
//            Map<Long, Object> map = new HashMap<>();
//            Map<Long, Object> mapBasic = new HashMap<>();
//            Map<String, Object> mapKnwSlotVo = new HashMap<>();
//            Map<String, Object> mapKnwSlotVoOther = new HashMap<>();
//            List<String> listStr  = new ArrayList<>();
//            String knNoumenonName = CharacterConstant.EMPTY;
//
//            // 处理选中，本体slot下存在编码体系SOID
//            String[] derailCodingSystemSoids;
//            Map<String, Object> mapDerailCodingSystemSoid = new HashMap<>();
//            if (StringUtils.isNotEmpty(individualParmVo.getDerailCodingSystemSoids())) {
//                derailCodingSystemSoids =
//                        individualParmVo.getDerailCodingSystemSoids().split(CharacterConstant.COMMA_SYMBOL);
//                for (String str :derailCodingSystemSoids) {
//                    mapDerailCodingSystemSoid.put(str, str);
//                }
//            }
//
//            // 处理选中本体slot的slotSoid
//            String[] slotSoids;
//            LinkedHashMap<String, Object> mapIndividualRules = new LinkedHashMap<>();
//            if (StringUtils.isNotEmpty(individualParmVo.getIndividualRules())) {
//                slotSoids =
//                        individualParmVo.getIndividualRules().split(CharacterConstant.UNDER_LINE);
//                for (String str :slotSoids) {
//                    if (StringUtils.isNotEmpty(str) && isNumeric(str)) {
//                        mapIndividualRules.put(str, CharacterConstant.EMPTY);
//                    } else {
//                        mapIndividualRules.put(str, str);
//                    }
//                }
//            }

        // 根据本体soid，取得本体SLOT以及相关编码体系下值集的列表
        List<KnwSlotVo> listKnwSlotVoTmp = null;
        try {
            listKnwSlotVoTmp = knwSlotMapper.getAllSlotVoByNoumenonSoid(individualParmVo.getNoumenonSoid());
            buildListSuccess(listResult, listKnwSlotVoTmp);
        } catch (Exception e) {
            log.error("实例列表生成异常", e);
            buildListWarn(listResult, "实例列表生成失败");
        }

//            // 遍历处理结果集
//            for (KnwSlotVo knwSlotVo : listKnwSlotVoTmp) {
//                // 基数MAP
//                if (mapBasic.get(knwSlotVo.getSlotSoid()) == null) {
//                    mapBasic.put(knwSlotVo.getSlotSoid(), knwSlotVo.getBasic());
//                }
//
//                // 编码体系为空的场合
//                if (knwSlotVo.getDerailCodingSystemSoid() == null
//                        || mapDerailCodingSystemSoid.get(knwSlotVo.getDerailCodingSystemSoid().toString()) == null) {
//                    // 没有编码体系的本体slot、map的SlotSoid设置
//                    if (map.get(knwSlotVo.getSlotSoid()) == null) {
//                        map.put(knwSlotVo.getSlotSoid(), knwSlotVo.getSlotSoid());
//                    }
//                    // 没有编码体系的本体slot、map的SLOT以及相关编码体系下值集的对象设置
//                    if (mapKnwSlotVoOther.get(knwSlotVo.getSlotSoid().toString()) == null) {
//                        mapKnwSlotVoOther.put(knwSlotVo.getSlotSoid().toString(), knwSlotVo);
//                    }
//                    continue;
//                }
//
//                if (mapKnwSlotVo.get(knwSlotVo.getSlotSoid()
//                        + CharacterConstant.SIGN_FOR_SUBTRACTION + knwSlotVo.getDataSetSoid()) == null) {
//                    mapKnwSlotVo.put(knwSlotVo.getSlotSoid()
//                            + CharacterConstant.SIGN_FOR_SUBTRACTION + knwSlotVo.getDataSetSoid(), knwSlotVo);
//                }
//
//                if (mapKnwSlotVo.get(knwSlotVo.getSlotSoid()) == null) {
//                    KnwSlotVo k = new KnwSlotVo();
//                    BeanUtils.copyProperties(knwSlotVo,  k);
//                    k.setDataSetSoid(null);
//                    k.setDataSetName(null);
//                    mapKnwSlotVo.put(knwSlotVo.getSlotSoid().toString(), k);
//                }
//
//                if (StringUtils.isEmpty(knNoumenonName)) {
//                    knNoumenonName = knwSlotVo.getNoumenonName();
//                }
//
//                if (map.get(knwSlotVo.getSlotSoid()) == null) {
//                    map.put(knwSlotVo.getSlotSoid(), knwSlotVo.getSlotSoid()
//                            + CharacterConstant.COMMA_SYMBOL + knwSlotVo.getSlotSoid()
//                            + CharacterConstant.SIGN_FOR_SUBTRACTION + knwSlotVo.getDataSetSoid());
//                } else {
//                    String str = (String) map.get(knwSlotVo.getSlotSoid());
//                    str += CharacterConstant.COMMA_SYMBOL + knwSlotVo.getSlotSoid()
//                            + CharacterConstant.SIGN_FOR_SUBTRACTION + knwSlotVo.getDataSetSoid();
//                    map.put(knwSlotVo.getSlotSoid(), str);
//                }
//            }
//
//            Map<String, Object> mapTmp = new HashMap<String, Object>();
//            Stack<String> stack;
//            arrayLists = new ArrayList<String[]>();
//            // 根据基数排列组合
//            for (Map.Entry<Long, Object> entry : map.entrySet()) {
//                String str =  String.valueOf(entry.getValue());
//                int basic  = (int) mapBasic.get(entry.getKey());
//                stack = new Stack<String>();
//                for (int i = 1; i <= basic ; i++) {
//                    getBasicList(str.split(CharacterConstant.COMMA_SYMBOL),i,0,0, mapTmp, stack);
//                }
//            }
//
//            // 转换基数排列组合后的结果集
//            for (Map.Entry<String, Object> entry : mapTmp.entrySet()) {
//                List<String> listTmp = (List<String>) entry.getValue();
//                String[] s = listTmp.stream().toArray(String[]::new);
//                arrayLists.add(s);
//            }
//
//            // 排列组合
//            doExchange(arrayLists);
//
//            // 实例列表
//            List<KnwIndividualVo> listKnwIndividualVo = new ArrayList<>();
//            // 实例对象
//            KnwIndividualVo knwIndividualVo = new KnwIndividualVo();
//            // 实例slot列表
//            List<KnwIndividualSoltVo> listKnwIndividualSoltVo =
//                    new ArrayList<KnwIndividualSoltVo>();
//            // 实例slot对象
//            KnwIndividualSoltVo knwIndividualSoltVo;
//            // 实例slot值列表
//            List<SoltVo> listSoltVo = new ArrayList<SoltVo>();
//            // 实例slot值对象
//            SoltVo soltVo;
//
//            // 遍历结果集设置返回前端的对象
//            if (arrayLists != null && arrayLists.size() > 0) {
//                Object object = arrayLists.get(0);
//
//                List<String[]> lists;
//                if (object instanceof String[]) {
//                    lists = new ArrayList<String[]>();
//                    String[] strs = (String[])object;
//                    for (String str:strs) {
//                        String[] strTmp = new String[1];
//                        strTmp[0] = str;
//                        lists.add(strTmp);
//                    }
//                } else {
//                    lists = (List<String[]>) object;
//                }
//
//                for (int i = 0; i < lists.size(); i++) {
//                    Object obj = lists.get(i);
//                    List<String> strList;
//                    if (obj instanceof String[]) {
//                        strList = new ArrayList<String>();
//                        String [] strTmp = lists.get(i);
//                        if (strTmp != null && strTmp.length > 0) {
//                            strList.add(strTmp[0]);
//                        }
//                    } else {
//                        strList = (List<String>) obj;
//                    }
//
//                    knwIndividualVo = new KnwIndividualVo();
//                    knwIndividualVo.setNoumenonSoid(individualParmVo.getNoumenonSoid());
//                    knwIndividualVo.setKnNoumenonName(knNoumenonName);
//                    listKnwIndividualSoltVo =
//                            new ArrayList<KnwIndividualSoltVo>();
//                    String individualName =  CharacterConstant.EMPTY;
//                    for (int j = 0; j < strList.size(); j++) {
//                        knwIndividualSoltVo = new KnwIndividualSoltVo();
//                        String str = strList.get(j);
//                        if (StringUtils.isNotEmpty(str)) {
//                            String[] strs = str.split(CharacterConstant.COMMA_SYMBOL);
//                            listSoltVo = new ArrayList<SoltVo>();
//                            KnwSlotVo knwSlotVo = new KnwSlotVo();
//                            for (String strTmp : strs) {
//                                soltVo = new SoltVo();
//                                if (mapKnwSlotVo.get(strTmp) != null) {
//                                    knwSlotVo= (KnwSlotVo) mapKnwSlotVo.get(strTmp);
//                                    soltVo.setBasic(Long.valueOf(knwSlotVo.getBasic()));
//                                    soltVo.setDataSetSoid(knwSlotVo.getDataSetSoid());
//                                    soltVo.setDataType(knwSlotVo.getDataType());
//                                    soltVo.setDataSetName(knwSlotVo.getDataSetName());
//                                    soltVo.setDerailCodingSystemSoid(knwSlotVo.getDerailCodingSystemSoid());
//                                    listSoltVo.add(soltVo);
//                                    if (knwSlotVo.getSlotSoid() != null) {
//                                        if (mapIndividualRules.get(knwSlotVo.getSlotSoid().toString()) != null) {
//                                            if (StringUtils.isNotEmpty(soltVo.getDataSetName())) {
//                                                String individualNameTmp = (String) mapIndividualRules.get(knwSlotVo.getSlotSoid().toString());
//                                                mapIndividualRules.put(knwSlotVo.getSlotSoid().toString(),
//                                                        individualNameTmp + soltVo.getDataSetName());
//                                            }
//                                        }
//                                    }
//                                    continue;
//                                }
//                                if (mapKnwSlotVoOther.get(strTmp) != null) {
//                                    knwSlotVo= (KnwSlotVo) mapKnwSlotVoOther.get(strTmp);
//                                    soltVo.setBasic(Long.valueOf(knwSlotVo.getBasic()));
//                                    soltVo.setDataType(knwSlotVo.getDataType());
//                                    soltVo.setDerailCodingSystemSoid(knwSlotVo.getDerailCodingSystemSoid());
//                                    listSoltVo.add(soltVo);
//                                }
//                            }
//
//                            knwIndividualSoltVo.setSlotSoid(knwSlotVo.getSlotSoid());
//                            knwIndividualSoltVo.setDerailCodingSystemSoid(knwSlotVo.getDerailCodingSystemSoid());
//                            knwIndividualSoltVo.setDataType(knwSlotVo.getDataType());
//                            knwIndividualSoltVo.setBasic(Long.valueOf(knwSlotVo.getBasic()));
//                            knwIndividualSoltVo.setList(listSoltVo);
//                        }
//                        listKnwIndividualSoltVo.add(knwIndividualSoltVo);
//                    }
//                    knwIndividualVo.setIndividualName(knNoumenonName);
//
//                    for (Map.Entry<String, Object> entry : mapIndividualRules.entrySet()) {
//                        individualName += entry.getValue();
//                        if (isNumeric(entry.getKey())) {
//                            entry.setValue(CharacterConstant.EMPTY);
//                        }
//                    }
//
//                    if (StringUtils.isNotEmpty(individualName)) {
//                        knwIndividualVo.setIndividualName(individualName);
//                    }
//
//                    knwIndividualVo.setListKnwIndividualSoltVo(listKnwIndividualSoltVo);
//                    listKnwIndividualVo.add(knwIndividualVo);
//                }
//            }

//            buildListSuccess(listResult, listKnwSlotVoTmp);
//        } catch (Exception e) {
//            log.error("实例列表生成异常", e);
//            buildListWarn(listResult, "实例列表生成失败");
//        } finally {
//            stopWatch.stop();
//            log.info("本次查询耗时:" + stopWatch.getTime() + "ms");
//        }

        return listResult;
    }

    /**
     * 判断是否是数字
     *
     * @param str
     * @return
     */
    private static boolean isNumeric(String str) throws Exception {
        Pattern pattern = Pattern.compile(CharacterConstant.REGEX_IS_NUM);
        return pattern.matcher(str).matches();
    }

    /**
     * @param shu  元素
     * @param targ 要选多少个元素
     * @param has  当前有多少个元素
     * @param cur  当前选到的下标
     */
    private void getBasicList(String[] shu, int targ, int has, int cur, Map<String, Object> mapTmp, Stack<String> stack) throws Exception {

        if (has == targ) {
            String str = stack.get(0);
            String[] strs = str.split(CharacterConstant.SIGN_FOR_SUBTRACTION);
            List<String> listStr = new ArrayList<>();
            String strTmp = "";
            if (mapTmp.get(strs[0]) == null) {
                listStr.add(stack.stream()
                        .collect(Collectors.joining(CharacterConstant.COMMA_SYMBOL)));
                mapTmp.put(strs[0], listStr);
            } else {
                listStr = (List<String>) mapTmp.get(strs[0]);
                listStr.add(stack.stream()
                        .collect(Collectors.joining(CharacterConstant.COMMA_SYMBOL)));
                mapTmp.put(strs[0], listStr);
            }

            return;
        }

        for (int i = cur; i < shu.length; i++) {
            if (!stack.contains(shu[i])) {
                stack.add(shu[i]);
                getBasicList(shu, targ, has + 1, i, mapTmp, stack);
                stack.pop();
            }
        }

    }

    /**
     * 排列组合
     *
     * @param arrayLists
     */
    private void doExchange(List arrayLists) throws Exception {

        int len = arrayLists.size();
        //判断数组size是否小于2，如果小于说明已经递归完成
        if (len < 2) {
            this.arrayLists = arrayLists;
            return;
        }
        //拿到第一个数组
        int len0;
        if (arrayLists.get(0) instanceof String[]) {
            String[] arr0 = (String[]) arrayLists.get(0);
            len0 = arr0.length;
        } else {
            len0 = ((ArrayList<String>) arrayLists.get(0)).size();
        }

        //拿到第二个数组
        String[] arr1 = (String[]) arrayLists.get(1);
        int len1 = arr1.length;

        //计算当前两个数组一共能够组成多少个组合
        int lenBoth = len0 * len1;

        //定义临时存放排列数据的集合
        ArrayList<ArrayList<String>> tempArrayLists = new ArrayList<>(lenBoth);

        //第一层for就是循环arrayLists第一个元素的
        for (int i = 0; i < len0; i++) {
            //第二层for就是循环arrayLists第二个元素的
            for (int j = 0; j < len1; j++) {
                //判断第一个元素如果是数组的场合
                if (arrayLists.get(0) instanceof String[]) {
                    String[] arr0 = (String[]) arrayLists.get(0);
                    ArrayList<String> arr = new ArrayList<>();
                    arr.add(arr0[i]);
                    arr.add(arr1[j]);
                    //把排列数据加到临时的集合中
                    tempArrayLists.add(arr);
                } else {
                    //上一轮的结果继续跟arrayLists的下一个元素排列
                    ArrayList<ArrayList<String>> arrtemp = (ArrayList<ArrayList<String>>) arrayLists.get(0);
                    ArrayList<String> arr = new ArrayList<>();
                    for (int k = 0; k < arrtemp.get(i).size(); k++) {
                        arr.add(arrtemp.get(i).get(k));
                    }
                    arr.add(arr1[j]);
                    tempArrayLists.add(arr);
                }
            }
        }

        //根据上面排列的结果重新生成的一个集合
        List newArrayLists = new ArrayList<>();
        //排列的数组装进来，前面两个数组不需要再加进来了
        for (int i = 2; i < arrayLists.size(); i++) {
            newArrayLists.add(arrayLists.get(i));
        }
        //数据加到新集合的第一位
        newArrayLists.add(0, tempArrayLists);

        //递归
        doExchange(newArrayLists);
    }


    private List<String> getList(List<String> list, int length) {
        return permutationNoRepeat(list, length);
    }

    /**
     * 排列组合(字符不重复排列)<br>
     * 内存占用：需注意结果集大小对内存的占用（list:10位，length:8，结果集:[10! / (10-8)! = 1814400]）
     *
     * @param list   待排列组合字符集合(忽略重复字符)
     * @param length 排列组合生成长度
     * @return 指定长度的排列组合后的字符串集合
     * @author www@yiynx.cn
     */
    private List<String> permutationNoRepeat(List<String> list, int length) {
        Stream<String> stream = list.stream().distinct();
        for (int n = 1; n < length; n++) {
            stream = stream.flatMap(str -> list.stream()
                    .filter(temp -> !str.contains(temp))
                    .map(str::concat));
        }
        return stream.collect(Collectors.toList());
    }


    /**
     * 保存实例slot
     *
     * @param actionResult 返回结果
     * @param t            实例bean
     * @param seq          实例soid
     * @return
     * @throws Exception
     */
    private Boolean SaveSlot(ActionResult actionResult, KnwIndividualVo t, Long seq) throws Exception {


        for (KnwIndividualSoltVo knwIndividualSoltVo : t.getListKnwIndividualSoltVo()) {
            KnwIndividualSolt knwIndividualSolt = new KnwIndividualSolt();
            if (knwIndividualSoltVo.getSlotSoid() == null) {
//                actionResult.setStatus(HttpStatus.OK.value());
//                actionResult.setMessage("本体Slot无效");
//                return true;
                throw new RuntimeException("本体Slot无效");
            }
            knwIndividualSolt.setIndividualSoid(seq);//实例soid
            knwIndividualSolt.setNoumenonSoid(t.getNoumenonSoid());//本体soid
            knwIndividualSolt.setSlotSoid(knwIndividualSoltVo.getSlotSoid());//本体slotSoid
            knwIndividualSolt.setStatus(t.getStatus());//实例slot状态
            knwIndividualSolt.setIsDelete(0L);
            knwIndividualSolt.setBasic(knwIndividualSoltVo.getBasic());//基数
            knwIndividualSolt.setDataType(knwIndividualSoltVo.getDataType());//Slot数值类型
            if (knwIndividualSoltVo.getList().size() != 0 && knwIndividualSoltVo.getDerailCodingSystemSoid() != null) {//插入值集

                for (SoltVo soltVo : knwIndividualSoltVo.getList()) {
                    knwIndividualSolt.setDataSetSoid(soltVo.getDataSetSoid());//值集soid
                    GaneratorSlot(knwIndividualSolt);
                }
            } else if (knwIndividualSoltVo.getList().size() != 0 && knwIndividualSoltVo.getDerailCodingSystemSoid() == null) {//插入文本

                for (SoltVo soltVo : knwIndividualSoltVo.getList()) {
                    knwIndividualSolt.setDataValue(soltVo.getDataValue());//数值
                    GaneratorSlot(knwIndividualSolt);
                }
            } else {

                GaneratorSlot(knwIndividualSolt);
            }
        }
        return false;
    }

    /**
     * 新增实例slot
     *
     * @param knwIndividualSolt 实例slotBean
     * @throws Exception
     */
    private void GaneratorSlot(KnwIndividualSolt knwIndividualSolt) throws Exception {
        Long seqSlot;
//        seqSlot = oIDGanerator.getSOID();
        seqSlot = soidService.getSoid();
        knwIndividualSolt.setIndividualSoltSoid(seqSlot);//实例Slot Soid
        knwIndividualSolt.setCreateDate(new Date());
        knwIndividualSolt.setUpdateDate(new Date());
        knwIndividualSoltMapper.insert(knwIndividualSolt);
        soidService.insertOid(seqSlot, 1);
//        String oidSlot = oIDGanerator.getOID(0);
//        DtOid dtOidSlot = new DtOid();
//        dtOidSlot.setOid(oidSlot);
//        dtOidSlot.setSoid(seqSlot);
//        dtOidMapper.insert(dtOidSlot);
    }
}
